
/*************
author:: libo
license:: MIT
*****************/
#ifndef LIB_CELL_MESH_FRAME_H_
#define LIB_CELL_MESH_FRAME_H_
#include "Cell_Traits.h"
/***********give some points p0 p1 ..pn then the
Antisymmetric tensor is

 (p1-p0)/\(p2-p0)/\...(pn-p0)*****

***/

#ifndef SAFE_FREE
#define SAFE_FREE(x) if(x!=NULL){free(x);x=NULL;}
#endif
#ifdef __cplusplus
extern "C"{
#endif
typedef struct Vertex{
    int id;
    double *point;
    int point_size;
   
    Node * cells;
    Node *faces;
    void *prop,*user_prop;
	VertexT traits;
}Vertex;

typedef struct HalfFace{
    int id;
    struct Vertex** vertices;
    int vertices_size;

    struct Cell* cell;
    struct Face* face;
    void *prop,*user_prop;
    HalfT traits;
}HalfFace;

typedef struct Face{
    int id;
    struct Vertex**vertices;
    int vertices_size;
    struct HalfFace* halffaces[2];
//int halffaces_size;

    void *prop,*user_prop;
    FaceT traits;
}Face;

typedef struct Cell{
    int id;

    struct Vertex**vertices;
    int vertices_size;
    Node* halffaces;
    void *prop,*user_prop;
    CellT traits;
}Cell;
//void Vertex_init_(Vertex*);
static inline void Vertex_init_(Vertex* pv)
{

    pv->cells=NULL;
    pv->faces=NULL;
    pv->id=-1;
    pv->point=NULL;
    pv->point_size=0;
    pv->prop=NULL;
    pv->user_prop=NULL;
    vertexT_init(&(pv->traits));
}
static inline void HalfFace_init_(HalfFace *hf)
{
    hf->vertices=NULL;
    hf->vertices_size=0;

    hf->cell=NULL;
    hf->face=NULL;
    hf->prop=NULL;
    hf->user_prop=NULL;
    hf->id=-1;
    halfT_init(&(hf->traits));
}


static inline void Face_init_(Face *f)
{
    f->prop=NULL;
    f->user_prop=NULL;
    f->vertices=NULL;
    f->id=-1;
    f->halffaces[0]=(template_hf*)malloc(sizeof(template_hf));
    f->halffaces[1]=(template_hf*)malloc(sizeof(template_hf));
    HalfFace_init_(f->halffaces[0]);
    HalfFace_init_(f->halffaces[1]);
    f->halffaces[0]->face=f;
    f->halffaces[1]->face=f;
     f->vertices_size=0;
    faceT_init(&(f->traits));
 
}
static inline void Cell_init_(Cell *pv)
{
    pv->vertices=NULL;
    pv->halffaces=NULL;
    pv->id=-1;
    pv->vertices_size=0;
    pv->prop=NULL;
    pv->user_prop=NULL;
    cellT_init(&(pv->traits));
}


static inline void free_Vertex(Vertex*v)
{   
    if(v->point!=NULL)
    {
        free(v->point);
        v->point=NULL;
    }
    if(v->faces!=NULL)
    {
        free_node(v->faces);
        v->faces=NULL;
    }
//free_node(v->faces);
    if(v->cells!=NULL)
    {
        free_node(v->cells);
        v->cells=NULL;
    }
    free(v);
}

static inline void free_HalfFace(HalfFace *hf)
{
    if(hf->vertices!=NULL)
    {
        free(hf->vertices);
        hf->vertices=NULL;
    }
    free(hf);

}

static inline void free_Face(Face*f)
{
    //printf("here1\n");
    if(f==NULL)
    {
        printf("cuowu\n");
        return;
    }
    if(f->vertices!=NULL)
    {
        free(f->vertices);
        f->vertices=NULL;
    }
    free_HalfFace(f->halffaces[0]);
    free_HalfFace(f->halffaces[1]);
    free(f);
}
static inline void free_Cell(Cell*c)
{
    if(c->vertices!=NULL)
    {
        free(c->vertices);
        c->vertices=NULL;
    }
    if(c->halffaces!=NULL)
    {
        free_node(c->halffaces);
        c->halffaces=NULL;
    }
    free(c);
}
static inline void Halfface_remove_c(HalfFace*hf,Cell*c)
{
    if(hf==NULL||c==NULL)
    {return;}
    if(hf->cell==c)
    {
        hf->cell=NULL;
    }
}



static inline void Face_remove_c(Face*f ,Cell*c)
{
    if(c==NULL)
    {
        return ;
    }
    if((f->halffaces[0])->cell==c)
    {
        ((template_hf*)f->halffaces[0])->cell=NULL;
    }
    else if(((template_hf*)f->halffaces[1])->cell==c)
    {
        ((template_hf*)f->halffaces[1])->cell=NULL;
    }
   
}
static inline void Vertex_remove_f(Vertex*v,Face*f)
{
    Node* node=node_find(v->faces,(void*)f);
    if(node==NULL)
    {
        return;
    }
    Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
    node1!=NULL?(node1->Next=node2):(v->faces=node2);
    
    if(node2!=NULL)
    {
        node2->Prev=(void*)node1;
    }
    free(node);
}
static inline void Vertex_remove_c(Vertex*v,Cell*c)
{
    Node* node=node_find(v->cells,(void*)c);
    if(node==NULL)
    {
        return;
    }
    Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
    node1!=NULL?(node1->Next=node->Next):(v->cells=node2);
    if(node2!=NULL)
    {
        node2->Prev=(void*)node1;
    }
    free(node);
}


static inline void Cell_remove_hf(Cell*c,HalfFace*f)
{
    Node*node=node_find(c->halffaces,(void*)f);
    if(node==NULL)
    {
        return;
    }
    Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
    node1!=NULL?(node1->Next=node2):(c->halffaces=node2);
    
    if(node2!=NULL)
    {
        node2->Prev=(void*)node1;
    }   
    free(node);
}

#ifdef __cplusplus
}
#endif
#endif
